package ma.cdm.compteRendu.services;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;

import ma.cdm.compteRendu.configuration.CRConfiguration;
import ma.cdm.compteRendu.dao.MembreComiteDAO;
import ma.cdm.compteRendu.dao.RoleDAO;
import ma.cdm.compteRenduVO.EntiteVO;
import ma.cdm.compteRenduVO.PersonneVO;
import ma.cdm.constantes.BundleGlobal;
import ma.cdm.constantes.Constantes;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;

import flex.messaging.FlexContext;

public class PersonneService {



	@Autowired
    private MembreComiteDAO membreComiteDAO;
	
	@Autowired
	private RoleDAO roleDAO;
	
	public RoleDAO getRoleDAO() {
		return roleDAO;
	}
	public void setRoleDAO(RoleDAO roleDAO) {
		this.roleDAO = roleDAO;
	}
	public MembreComiteDAO getMembreComiteDAO() {
		return membreComiteDAO;
	}
	public void setMembreComiteDAO(MembreComiteDAO membreComiteDAO) {
		this.membreComiteDAO = membreComiteDAO;
	}
	
	public PersonneVO getPersonneShortData(String matricule)
	{
		PersonneVO personne ;
		try{
      	    LdapContext ctx = null;  
            Hashtable<String, String> env = new Hashtable<String, String>();  
            env.put(Context.INITIAL_CONTEXT_FACTORY,  "com.sun.jndi.ldap.LdapCtxFactory");  
            env.put(Context.SECURITY_AUTHENTICATION, "Simple");  
            env.put(Context.PROVIDER_URL,Constantes.getString(CRConfiguration.LDAP_PROVIDER_URL,BundleGlobal.BUNDLE_NAME));  
            ctx = new InitialLdapContext(env, null);
            Attributes attrs = ctx.getAttributes("uid="+matricule+","+Constantes.getString(CRConfiguration.LDAP_USERS_DN,BundleGlobal.BUNDLE_NAME));           
            personne = new PersonneVO();
            personne.setCivilite(attrs.get("personalTitle").get().toString());
            personne.setMatricule(attrs.get("uid").get().toString());
            personne.setMail(attrs.get("mail").get().toString());
            personne.setNom(attrs.get("sn").get().toString());
            personne.setPrenom(attrs.get("givenName").get().toString());
            personne.setPresent(false);
            if(attrs.get("departmentNumber") != null && attrs.get("departmentNumber").get() != null)
            {
            	personne.setDepartement(getDepartement(attrs.get("departmentNumber").get().toString()));
            }          
            return personne;
        }catch(NamingException nex){
            System.out.println("LDAP Connection: FAILED");  
            return null;
        }  
	}
	private String getDepartement(String departementCode) {
		
		try {
			LdapContext ctx = null;  
            Hashtable<String, String> env = new Hashtable<String, String>();  
            env.put(Context.INITIAL_CONTEXT_FACTORY,  "com.sun.jndi.ldap.LdapCtxFactory");  
            env.put(Context.SECURITY_AUTHENTICATION, "Simple");  
            env.put(Context.PROVIDER_URL, Constantes.getString(CRConfiguration.LDAP_PROVIDER_URL,BundleGlobal.BUNDLE_NAME));  
            ctx = new InitialLdapContext(env, null);  
            Attributes attrs = ctx.getAttributes("ou="+departementCode+","+Constantes.getString(CRConfiguration.LDAP_UNITS_DN,BundleGlobal.BUNDLE_NAME));    
		   if(attrs != null && attrs.get("cn") != null && attrs.get("cn").get() != null)
		   {
			   return attrs.get("cn").get().toString();
		   }
		} catch (Exception e) {
			return departementCode;
		}
		return null;
	}
	
	public PersonneVO getPersonneData(String matricule)
	{
		if(matricule == null)
		{
			PersonneVO personne = new PersonneVO(); 
			personne.setImage(getImage(matricule));
			return personne;
		}
		PersonneVO personne ;
		try{
      	    LdapContext ctx = null;  
            Hashtable<String, String> env = new Hashtable<String, String>();  
            env.put(Context.INITIAL_CONTEXT_FACTORY,  "com.sun.jndi.ldap.LdapCtxFactory");  
            env.put(Context.SECURITY_AUTHENTICATION, "Simple");  
            env.put(Context.PROVIDER_URL, Constantes.getString(CRConfiguration.LDAP_PROVIDER_URL,BundleGlobal.BUNDLE_NAME));  
            ctx = new InitialLdapContext(env, null);  
            Attributes attrs = ctx.getAttributes("uid="+matricule+","+Constantes.getString(CRConfiguration.LDAP_USERS_DN,BundleGlobal.BUNDLE_NAME));           
            personne = new PersonneVO();
            personne.setCivilite(attrs.get("personalTitle").get().toString());
            personne.setCompany(attrs.get("o").get().toString());
            //personne.setDepartement(attrs.get("departmentNumber").get().toString());
            personne.setFonction(attrs.get("title").get().toString());
            personne.setMail(attrs.get("mail").get().toString());
            personne.setMatricule(attrs.get("uid").get().toString());
            personne.setNom(attrs.get("sn").get().toString());
            personne.setPrenom(attrs.get("givenName").get().toString());
            personne.setImage(getImage(matricule));
            if(attrs.get("departmentNumber") != null && attrs.get("departmentNumber").get() != null)
            {
            	personne.setDepartement(getDepartement(attrs.get("departmentNumber").get().toString()));
            } 
            return personne;
        }catch(NamingException nex){
            System.out.println("LDAP Connection: FAILED");  
            return null;
        }  
	}
	
	public List<PersonneVO> searchPersonne(String matricule,String nom, String prenom)
	{
		List<PersonneVO> personnes = new ArrayList<PersonneVO>();
		if(matricule == null)
		{
			matricule = "";
		}
	
	    matricule = matricule.toLowerCase();
	
		
		if(!matricule.startsWith("cdm-"))
		{
			matricule = "cdm-u"+matricule;
		}

		try {
			  LdapContext ctx = null;  
	          Hashtable<String, String> env = new Hashtable<String, String>();  
	          env.put(Context.INITIAL_CONTEXT_FACTORY,  "com.sun.jndi.ldap.LdapCtxFactory");  
	          env.put(Context.SECURITY_AUTHENTICATION, "Simple");  
	          env.put(Context.PROVIDER_URL, Constantes.getString(CRConfiguration.LDAP_PROVIDER_URL,BundleGlobal.BUNDLE_NAME));  
	          ctx = new InitialLdapContext(env, null);  

			    String base = Constantes.getString(CRConfiguration.LDAP_USERS_DN,BundleGlobal.BUNDLE_NAME);
			    SearchControls sc = new SearchControls();
			    sc.setSearchScope(SearchControls.SUBTREE_SCOPE);

			    String filter = "(&(uid="+matricule+"*)(sn="+nom+"*)(givenName="+prenom+"*))";

			    NamingEnumeration<SearchResult> results = ctx.search(base, filter, sc);
			    while (results.hasMore()) {
			      SearchResult sr = (SearchResult) results.next();
			        Attributes attrs = sr.getAttributes();
			        try {
			        	    PersonneVO personne = new PersonneVO();
				            personne.setCivilite(attrs.get("personalTitle").get().toString());
				            personne.setMatricule(attrs.get("uid").get().toString());
				            personne.setNom(attrs.get("sn").get().toString());
				            personne.setPrenom(attrs.get("givenName").get().toString());
				            personne.setMail(attrs.get("mail").get().toString());
				            personnes.add(personne);	
					} catch (Exception e) {
					}
			      	            
			    }
			    ctx.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return personnes;
	}
	public static void main(String[] args) {
		PersonneService ps = new PersonneService();
		List<EntiteVO> entities = ps.searchEntite("", "", "", "");
		Map<String, String> a = new HashMap<String, String>();
		for (EntiteVO entiteVO : entities) {
			if(!a.containsKey(entiteVO.getType().toLowerCase()))
			{  System.out.print(entiteVO.getType().toUpperCase().substring(0, 1));
				System.out.println(entiteVO.getType().toLowerCase().substring(1, entiteVO.getType().toLowerCase().length()));
				a.put(entiteVO.getType().toLowerCase(), entiteVO.getType().toLowerCase());
			}
			
		}
		//System.out.println(entities.size());
	}
	public List<EntiteVO> searchEntite(String code,String type,String nom,String societe)
	{
	
		try {
			List<EntiteVO> entities = new ArrayList<EntiteVO>();
			  LdapContext ctx = null;  
	          Hashtable<String, String> env = new Hashtable<String, String>();  
	          env.put(Context.INITIAL_CONTEXT_FACTORY,  "com.sun.jndi.ldap.LdapCtxFactory");  
	          env.put(Context.SECURITY_AUTHENTICATION, "Simple");  
	          env.put(Context.PROVIDER_URL,Constantes.getString(CRConfiguration.LDAP_PROVIDER_URL,BundleGlobal.BUNDLE_NAME));  
	          ctx = new InitialLdapContext(env, null);  

			    String base =Constantes.getString(CRConfiguration.LDAP_UNITS_DN,BundleGlobal.BUNDLE_NAME);
			    SearchControls sc = new SearchControls();
			    sc.setSearchScope(SearchControls.SUBTREE_SCOPE);

			    String filter = "(&(ou="+code+"*)(cn="+nom+"*)(businessCategory="+type+"*)(o="+societe+"*))";

			    NamingEnumeration<SearchResult> results = ctx.search(base, filter, sc);
			    while (results.hasMore()) {
			      SearchResult sr = (SearchResult) results.next();
			        Attributes attrs = sr.getAttributes();
			        try {
			        	EntiteVO entite = new EntiteVO();
			        	entite.setCode(attrs.get("ou").get().toString());
			        	entite.setLieu(attrs.get("l").get().toString());
			        	entite.setNom(attrs.get("cn").get().toString());
			        	entite.setType(attrs.get("businessCategory").get().toString());
			        	Attribute attrResponsable = attrs.get("camanagementindication");
			        	if(attrResponsable != null && attrResponsable.get() != null )
			        	{
			        		//Exemple :  DIRECTEUR D'AGENCE$uid=cdm-u2311,ou=People,o=CDM,o=Credit Agricole$1			        		
			        		String responsableStr =  attrResponsable.get().toString();
			        		if(responsableStr != null)
			        		{
			        			//System.out.println(responsableStr);
			        			String [] tokens = responsableStr.split("$");
			        			if(tokens != null && tokens.length  == 2)
			        			{
			        				String matricule  = tokens[1].split(",")[0];
			        				//entite.setResponsable(getPersonneData(matricule));
			        			}
			        		}			        		
			        	}
				            entities.add(entite);					           
					} catch (Exception e) {
						return null;
					}			      	            
			    }			    
			    ctx.close();
			    return entities;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
   public byte[] getImage(String matricule)
   
   {
	   try {
		   String url =Constantes.getString(CRConfiguration.LDAP_IMAGE_URL,BundleGlobal.BUNDLE_NAME) +"personneDn=uid="+matricule+",ou=People,o=CDM,o=Credit%20Agricole";
	       java.io.InputStream in = (new URL( url)).openStream();
		   byte[] b = IOUtils.toByteArray(in);
		   in.close();
	       return b;
	   }
	   catch (IOException e) {
		   if(e.getMessage().startsWith("Server returned HTTP response code: 500"))
		   {
			   try {
				   return  FileUtils.readFileToByteArray(new File(FlexContext.getServletContext().getRealPath("images")+File.separator+"no-body.png"));
			} catch (Exception ex) {
				ex.printStackTrace();
			}		  
		   }
		   else
		   {
			   e.printStackTrace ();
		   }
	     
	   }
	   
	   return null;
   }
}
